/*
 * @Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved.
 */

#include <vector>
#include <iostream>
#include <string>
#include "include/securec.h"
#include "include/tar.h"

class OHOStar {
public:
    OHOStar() {}

    ~OHOStar()
    {
        FreeTar();
    }

    static OHOStar& GetInstance()
    {
        static OHOStar* instance;  // 单例
        if (instance == nullptr) {
            instance = new OHOStar();
        }
        return *instance;
    }

    static OHOStar& FreeInstance()
    {
        OHOStar *instance = &GetInstance(); // 拿出单例
        if (instance == nullptr) {
            delete instance;    // 释放单例
        }
        return *instance;
    }

    void setTarRootPath(std::string Path) // 1
    {
        rootPath = Path;
    }

    std::string getTarRootPath ()
    {
        return rootPath;
    }

    void addTarpath(std::string path)// 1
    {
        // 上层不能保证不会重复，需要自己重新去检验
        std::vector < std::string >::iterator it;   // 声明一个迭代器，来访问vector容器，作用：遍历或者指向vector容器的元素
        for (it = TarPath.begin(); it != TarPath.end(); it++) {
            if (path == *it) {
                // 如果存在删除原来的
                it = TarPath.erase(it);
            }
        }
        // 重新添加
        TarPath.push_back(path);
        mark = true;    // 发生修改进行标记
    }

    void delTarpath(std::string path)
    {
        std::vector < std::string >::iterator it;   // 声明一个迭代器，来访问vector容器，作用：遍历或者指向vector容器的元素
        for (it = TarPath.begin(); it != TarPath.end(); it++) {
            if (path != *it) {
                it = TarPath.erase(it);
                mark = true;    // 发生修改进行标记
            }
        }
    }

    // 释放 char** 的内存
    void FreeCString(char** destination, int size)
    {
        if (destination == nullptr) {
            return;
        }
        for (int n = 0; n < size; n++) {
            delete destination[n];
            destination[n] = nullptr;
        }
        destination = nullptr;
    }

    // 将 vector中的所有string 转为一个 char**
    void MakeCString(const std::vector < std::string >& source, char**& destination)
    {
        // 释放资源
        FreeCString(destination, static_cast < int > (source.size()));
        // 注意释放内存
        destination = new char *[static_cast < int > (source.size())];
        std::string desStr;
        size_t strLen;
        errno_t err = EOK;
        for (int n = 0; n < static_cast<int>(source.size()); ++n) {
            if (access(source[n].c_str(), F_OK) != -1) {
                desStr = source[n];
            } else {
                desStr = rootPath + "/" + source[n];
            }
            strLen = desStr.size() + 1;
            destination[n] = new char[strLen];
            err = strcpy_s(destination[n], strLen, desStr.c_str());
            if (err != EOK) {
                continue;
            }
        }
    }

    char **GetTarPaths()
    {
        if (mark) { // 判断是否发生修改
            MakeCString(TarPath, cTarPath);
        }
        mark = false;   // 重置修改状态
        return cTarPath;
    }

    int GetTarPathCount()
    {
        return TarPath.size();
    }

    std::string getcommendPath()
    {
        std::string commend = "";
        std::vector < std::string >::iterator it;   // 声明一个迭代器，来访问vector容器，作用：遍历或者指向vector容器的元素
        for (it = TarPath.begin(); it != TarPath.end(); it++) {
            commend += "./" + (*it) + " ";
        }
        return commend;
    }

    void FreeTar()
    {
        if (cTarPath != nullptr) {
            FreeCString(cTarPath, static_cast < int > (TarPath.size()));
        }
        TarPath.clear();
        mark = true;
    }

    std::string rootPath; // 不能清除
private:
    std::vector<std::string> TarPath;
    char **cTarPath = nullptr;
    bool mark = true;
};


extern "C" {   // cangjie ffi

const int64_t cj_get_c_tar();
void cj_set_tar_root_path(const int64_t ptr, char* p);
void cj_add_tar_path(const int64_t ptr, char* p);
long long cj_si_tar(const int64_t ptr, char* p);
long long cj_si_un_tar(char* tar_file_name, char* p);
void cj_free_c_tar(const int64_t ptr);

const int64_t cj_get_c_tar()  // 获取 c tar 类对象指针
{
    OHOStar* instance;
    instance = new OHOStar();
    return (int64_t)instance;
}

OHOStar* get_native_c_tar(const int64_t ptr) 
{
    if (ptr == 0) {
        throw std::invalid_argument("Pointer is null");
    }
    OHOStar* instance;
    instance = (OHOStar*)ptr;
    return instance;  
}

void cj_set_tar_root_path(const int64_t ptr, char* p) 
{
    OHOStar* instance = get_native_c_tar(ptr);
    std::string path = p;
    instance->setTarRootPath(path);  // 指针 仓颉侧调用释放
    set_rootPath(instance->rootPath);
}

void cj_add_tar_path(const int64_t ptr, char* p) 
{
    OHOStar* instance = get_native_c_tar(ptr);
    std::string path = p;
    instance->addTarpath(path);  // 指针 仓颉侧调用释放
}

long long cj_si_tar(const int64_t ptr, char* p)
{
    OHOStar* instance = get_native_c_tar(ptr);
    int res = -1;
    if (instance->GetTarPathCount() <= 0) {
        return res;
    }
    res = Tar(p, instance->GetTarPaths(), instance->GetTarPathCount());  // 指针 仓颉侧调用释放
    return res;
}

long long cj_si_un_tar(char* tar_file_name, char* p) 
{
    char **unTarPath = new char *[1];
    unTarPath[0] = p;
    int res = -1;
    res = UnTar(tar_file_name, unTarPath, 0);   // 0 表示tar中文件全部提取出来. 
    unTarPath = nullptr;
    return res;
}

void cj_free_c_tar(const int64_t ptr)  // 指针 仓颉侧调用释放
{
    OHOStar* instance = get_native_c_tar(ptr);
    instance->FreeTar();
}


} // extern "C" { 

